--[[
DlgMgr:
对话管理器
--]]

-- class
DlgMgr = DefineClass(
{
    _DlgTypes = { };
    _Dlgs = Vector:new();
    _TmpDlgs = Vector:new();
} );

-- 初始化管理器
function DlgMgr:Init()
end

-- 当前窗口信息
-- return: dlgNum，hideNum，closedNum，detailInfo
function DlgMgr:DlgInfo(detailed)
    local num = 0;
    local hideNum = 0;
    local closedNum = 0;
    local detailInfo = "";
    if detailed then
        for i = 1, self._Dlgs:Size() do
            local dlg = self._Dlgs:At(i);
            detailInfo = detailInfo .. "\n" .. dlg:GetDlgType();
            if dlg:IsValid() then
                num = num + 1;
                if not dlg:IsVisible() then
                    hideNum = hideNum + 1;
                    detailInfo = detailInfo .. " (隐藏)";
                end
            else
                closedNum = closedNum + 1;
                detailInfo = detailInfo .. " (已关闭)";
            end
        end
    else
        for i = 1, self._Dlgs:Size() do
            local dlg = self._Dlgs:At(i);
            if dlg:IsValid() then
                num = num + 1;
                if not dlg:IsVisible() then
                    hideNum = hideNum + 1;
                end
            else
                closedNum = closedNum + 1;
            end
        end
    end
    detailInfo = "窗口数:" .. num .. "  隐藏数:" .. hideNum .. "  已关闭:" .. closedNum .. detailInfo;
    return num, hideNum, closedNum, detailInfo;
end

function DlgMgr:DlgHideNum()
end

function DlgMgr:DlgClosedNum()
end

-- 注册一个类
function DlgMgr:RegisterDlg(DlgClass, dlgClassName)
    self._DlgTypes[dlgClassName] = DlgClass;
end

-- 通过类名反射一个dlg类（table）
-- dlgClassName: 类名
-- return: 返回对应的类（的table），如果没有返回null
function DlgMgr:FindDlgClass(dlgClassName)
    return self._DlgTypes[dlgClassName];
end

-- 打开|关闭 界面切换：如果界面已打开，就关闭它；如果未打开，就打开它
-- DlgClass: 对话框类
-- return: 打开的话，返回窗口，关闭则返回nil
function DlgMgr:ToggleDlg(DlgClass, args)
    local dlg = self:GetDlg(DlgClass);
    if dlg == nil then
        return self:FetchShowDlg(DlgClass, args);
    else
        dlg:Close();
        return nil;
    end
end

-- 获取一个给定类型的dialog，如果不存在就创建一个，并且强制显示出来
-- DlgClass: dialog类型
-- args：初始化参数，可能是一个table
-- return: 给定类型对话的实例
function DlgMgr:FetchShowDlg(DlgClass, args)
    local dlg = self:GetDlg(DlgClass);
    if dlg == nil then
        dlg = self:_CreateDlg(DlgClass, args);
    end
    if dlg ~= nil then
        dlg:Show();
    end
    return dlg;
end

-- 获取一个给定类型的dialog，如果不存在就创建一个
-- DlgClass: dialog类型
-- args：初始化参数，可能是一个table
-- return: 给定类型对话的实例
function DlgMgr:FetchDlg(DlgClass, agrs)
    local dlg = self:GetDlg(DlgClass);
    if dlg == nil then
        dlg = self:_CreateDlg(DlgClass, agrs);
    end
    return dlg;
end

-- 创建一个全新的给定类型的Dialog实例
-- DlgClass: dialog类型
-- args：初始化参数，可能是一个table
-- return: 新实例
function DlgMgr:CreateDlg(DlgClass, args)
    return self:_CreateDlg(DlgClass, args);
end

-- 创建一个全新的给定类型的Dialog实例，作为子窗口
-- pareantWin: 父窗口
-- parentNode: 新建的窗口的挂载节点
-- DlgClass: dialog类型
-- args：初始化参数，可能是一个table
-- return: 新实例
function DlgMgr:CreateSubDlg(parentWin, parentNode, DlgClass, args)
    return self:_CreateSubDlg(parentWin, parentNode, DlgClass, args);
end

-- 获取给定id的对话实例
-- dlgID: 对话id
-- return: 实例，如果不存在该id，返回nil
function DlgMgr:GetDlgByID(dlgID)
    local i = 1;
    while i <= self._Dlgs:Size() do
        local dlg = self._Dlgs:At(i);
        if dlg:IsValid() and dlg:GetID() == dlgID then
            return dlg;
        end
        i = i + 1;
    end
    return nil;
end

-- 获取第一个找到的给定类型的对话实例
-- DlgClass: 对话类型
-- return：对话实例，没有找到返回nil
function DlgMgr:GetDlg(DlgClass)
    if not DlgClass then
        return nil;
    end
    local typeName = DlgClass:GetDlgType();
    return self:GetDlgByClassName(typeName);
end

-- 获取第一个找到的给定类型的对话实例
-- DlgClassName: 对话类型名称
-- return：对话实例，没有找到返回nil
function DlgMgr:GetDlgByClassName(DlgClassName)
    local typeName = DlgClassName;
    if self._Dlgs:Size() == 0 then
        return nil;
    end;
    local i = 1;
    while i <= self._Dlgs:Size() do
        local dlg = self._Dlgs:At(i);
        if dlg:IsValid() and dlg:GetDlgType() == typeName then
            return dlg;
        end
        i = i + 1;
    end
    return nil;
end

-- 获取给定类型对话的所有实例
-- DlgClass: 对话类型
-- return：对话实例数组（Vector），如果没有，返回长度为0的数组
function DlgMgr:GetDlgList(DlgClass)
    local typeName = DlgClass:GetDlgType();
    local v = Vector:new();
    local i = 1;
    while i <= self._Dlgs:Size() do
        local dlg = self._Dlgs:At(i);
        if dlg:IsValid() and dlg:GetDlgType() == typeName then
            v:PushBack(dlg);
        end
        i = i + 1;
    end
    return v;
end

-- 隐藏全部Dlg
function DlgMgr:HideAllDlg()
    local i = 1;
    while i <= self._Dlgs:Size() do
        local dlg = self._Dlgs:At(i);
        if dlg:IsValid() then
            dlg:SetVisible(false);
        end
        i = i + 1;
    end
end

function DlgMgr:HideAllDlgIF(funcObj)
    local i = 1;
    local dlgVec = Vector:new();
    while i <= self._Dlgs:Size() do
        local dlg = self._Dlgs:At(i);
        if dlg:IsValid() and funcObj(dlg) == true and dlg:IsVisible() then
            dlg:SetVisible(false);
            dlgVec:PushBack(dlg);
        end
        i = i + 1;
    end
    return dlgVec;
end


-- 显示全部Dlg
function DlgMgr:ShowAllDlg()
    local i = 1;
    while i <= self._Dlgs:Size() do
        local dlg = self._Dlgs:At(i);
        if dlg:IsValid() then
            dlg:SetVisible(true);
        end
        i = i + 1;
    end
end
-- 关闭给定id的对话实例
-- dlgID: 对话id
function DlgMgr:CloseDlgByID(dlgID)
    local dlg = self:GetDlgByID(dlgID);
    if dlg ~= nil then
        dlg:Close();
    end
end

-- 关闭第一个找到的给定类型的对话实例
-- DlgClass: 对话类型
function DlgMgr:CloseDlg(DlgClass)
    local dlg = self:GetDlg(DlgClass);
    if dlg ~= nil then
        dlg:Close();
    end
end

function DlgMgr:CloseDlgIF(funcObj)
    local i = 1;
    while i <= self._Dlgs:Size() do
        local dlg = self._Dlgs:At(i);
        if funcObj(dlg) == true then
            dlg:Close();
        end
        i = i + 1;
    end
end

-- 显示第一个找到的给定类型的对话实例
function DlgMgr:ShowDlg(DlgClass)
    local dlg = self:GetDlg(DlgClass);
    if dlg == nil then
        dlg = self:FetchDlg(DlgClass);
    end

    if dlg ~= nil then
        dlg:Show();
    end
    return dlg;
end

-- 隐藏第一个找到的给定类型的对话实例
function DlgMgr:HideDlg(DlgClass)
    local dlg = self:GetDlg(DlgClass);
    if dlg ~= nil then
        dlg:Hide();
    end
end

-- 关闭给定类型对话的所有实例
-- DlgClass: 对话类型
-- return：被关闭的实例数量
function DlgMgr:CloseDlgList(DlgClass)
    local dlgs = self:GetDlgList(DlgClass);
    local num = 0;
    local i = 1;
    while i <= dlgs:Size() do
        local dlg = dlgs:At(i);
        if dlg:IsValid() and dlg:GetDlgType() == typeName then
            dlg:Close();
            num = num + 1;
        end
        i = i + 1;
    end
    return num;
end

-- 关闭当前所有对话实例
function DlgMgr:CloseAllDlgs()
    self._Dlgs:CopyTo(self._TmpDlgs);
    local i = 1;
    while i <= self._TmpDlgs:Size() do
        local dlg = self._TmpDlgs:At(i);
        dlg:Close();
        self:_RemoveDlg(dlg);
        i = i + 1;
    end
    self._Dlgs:Clear();
    self._TmpDlgs:Clear();
end



-- 每帧更新所有对话
function DlgMgr:Update()
    self._Dlgs:CopyTo(self._TmpDlgs);
    local i = 1;
    while i <= self._TmpDlgs:Size() do
        local dlg = self._TmpDlgs:At(i);
        if dlg:IsClosed() then
            self:_RemoveDlg(dlg);
        else
            if dlg:CanClose() then
                dlg:Close();
            else
                if dlg.OnUpdate ~= nil and dlg:IsVisible() then
                    dlg:OnUpdate();
                end
            end
        end
        i = i + 1;
    end
    self._TmpDlgs:Clear();
end

-- 处理f7加速
function DlgMgr:HandleF7()
    for i = 1, self._Dlgs:Size() do
        local dlg = self._Dlgs:At(i);
        if dlg:IsValid() and dlg:OnF7() then
            return;
        end
    end
end

function DlgMgr:_CreateDlg(DlgClass, args)
    local dlg = DlgClass:new();
    self:_InsertDlg(dlg);
    dlg:Init(args);
    if dlg:IsClosed() then
        self:_RemoveDlg(dlg);
        return nil;
    end
    return dlg;
end

function DlgMgr:_CreateSubDlg(parentWin, parentNode, DlgClass, args)
    local dlg = DlgClass:new();
    self:_InsertDlg(dlg);
    dlg:InitAsSubDlg(parentWin, parentNode, args);
    if dlg:IsClosed() then
        self:_RemoveDlg(dlg);
        return nil;
    end
    return dlg;
end

function DlgMgr:_InsertDlg(dlg)
    self._Dlgs:PushBack(dlg);
end

function DlgMgr:_RemoveDlg(dlg)
    self._Dlgs:Remove(dlg);
    dlg:Gabage();
end

